package com.hnec.dms.log.service;

import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import com.hnec.dms.log.operation.OpLogForm;
import com.hnec.dms.log.operation.OpLogInnerForm;
import com.hnec.dms.log.operation.OpUserInfo;
import com.hnec.dms.log.env.LogEnv;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;

import com.alibaba.fastjson.JSONObject;
import com.hnec.dms.base.data.TransData;
import com.hnec.dms.log.cons.LogCons;

/**
 * 操作日志记录工具类
 *
 * @Author hidebug
 */
public abstract class AbstractOpLogService implements OpLogService {

	private static final Logger loggerOpLog = LoggerFactory.getLogger(LogCons.OP_LOGGER_NAME);

	private static final Logger logger = LoggerFactory.getLogger(AbstractOpLogService.class);

	/**
	 * 记录操作日志
	 * <p>
	 * 这个方法不能抛出任何异常
	 *
	 * @param opLogForm 日志参数
	 */
	@Override
	public void logOperation(OpLogForm opLogForm) {
		try {
			OpLogInnerForm opLogInnerForm = TransData.transProperties(opLogForm, OpLogInnerForm.class);

			opLogInnerForm.setAppName(LogEnv.getApp());

			// TODO 如果在异步线程httpcontext 获取会抛出空指针异常，后续持续观察场景
			HttpServletRequest request = LogEnv.getHttpServletRequest();
			if (request != null) {
				opLogInnerForm.setServerIp(request.getLocalAddr());
				opLogInnerForm.setClientIp(LogEnv.getClientIp(request));
				opLogInnerForm.setUri(request.getRequestURI());
			}

			// 设置用户信息
			OpUserInfo opUserInfo = getOpUserInfo();
			if (opUserInfo != null) {
				opLogInnerForm.setShopId(opUserInfo.getShopId());
				opLogInnerForm.setUserId(opUserInfo.getUserId());
				opLogInnerForm.setUserName(opUserInfo.getUserName());
			}

			Map<String, Object> mapInfo = JSONObject.parseObject(JSONObject.toJSONString(opLogInnerForm));
			mapInfo.forEach((key, value) -> {
				MDC.put(key, String.valueOf(value));
			});

			loggerOpLog.info(opLogInnerForm.getAppName() + "_" + opLogForm.getModule() + "_oplog");
			
			//清除附加信息
			MDC.clear();

		} catch (Exception e) {
			logger.error("log operation error", e);
		}
	}

	/**
	 * 获得操作用户信息
	 * 
	 * @return
	 */
	public abstract OpUserInfo getOpUserInfo();
}
